package com.ethanhua.skeleton;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;

import androidx.annotation.ColorRes;
import androidx.annotation.IntRange;
import androidx.annotation.LayoutRes;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import com.facebook.shimmer.Shimmer;
import com.facebook.shimmer.ShimmerFrameLayout;


/**
 * Created by ethanhua on 2017/7/29.
 */

public class ViewSkeletonScreen implements SkeletonScreen, LifecycleObserver {
    private static final String TAG = ViewSkeletonScreen.class.getName();
    private final ViewReplacer mViewReplacer;
    private final View mActualView;
    private final int mSkeletonResID;
    private final int mShimmerColor;
    private final boolean mShimmer;
    private final int mShimmerDuration;
    private final int mShimmerAngle;

    private boolean isViewShowing = false;

    private ViewSkeletonScreen(Builder builder) {
        mActualView = builder.mView;
        mSkeletonResID = builder.mSkeletonLayoutResID;
        mShimmer = builder.mShimmer;
        mShimmerDuration = builder.mShimmerDuration;
        mShimmerAngle = builder.mShimmerAngle;
        mShimmerColor = builder.mShimmerColor;
        mViewReplacer = new ViewReplacer(builder.mView);
        if (builder.lifecycleRegistry != null)
            builder.lifecycleRegistry.addObserver(this);
    }

    private View generateShimmerContainerLayout(ViewGroup parentView) {
        View rootView = LayoutInflater.from(mActualView.getContext()).inflate(R.layout.layout_shimmer, parentView, false);
        final ShimmerFrameLayout shimmerViewContainer = rootView.findViewById(R.id.shimmer_view_container);
        final FrameLayout contentContainer = rootView.findViewById(R.id.content);
        shimmerViewContainer.setShimmer(new Shimmer.ColorHighlightBuilder()
                .setHighlightColor(mShimmerColor) //闪烁的颜色
                .setDuration(mShimmerDuration)
                .setTilt(mShimmerAngle)
                .setDirection(Shimmer.Direction.LEFT_TO_RIGHT)
                .setBaseAlpha(0f)
                .setHighlightAlpha(1f)
                .build());

        View innerView = LayoutInflater.from(mActualView.getContext()).inflate(mSkeletonResID, contentContainer, false);
        contentContainer.setLayoutParams(new ConstraintLayout.LayoutParams(innerView.getLayoutParams()));
        contentContainer.addView(innerView);
//        shimmerViewContainer.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
//            @Override
//            public void onViewAttachedToWindow(View v) {
//                shimmerViewContainer.startShimmer();
//            }
//
//            @Override
//            public void onViewDetachedFromWindow(View v) {
//                shimmerViewContainer.stopShimmer();
//            }
//        });
//        shimmerViewContainer.startShimmer();
        return rootView;
    }

    private View generateSkeletonLoadingView() {
        ViewParent viewParent = mActualView.getParent();
        if (viewParent == null) {
            Log.e(TAG, "the source view have not attach to any view");
            return null;
        }
        ViewGroup parentView = (ViewGroup) viewParent;
        if (mShimmer) {
            return generateShimmerContainerLayout(parentView);
        }
        return LayoutInflater.from(mActualView.getContext()).inflate(mSkeletonResID, parentView, false);
    }

    @Override
    public void show() {
        View skeletonLoadingView = generateSkeletonLoadingView();
        if (skeletonLoadingView != null) {
            mViewReplacer.replace(skeletonLoadingView);
        }
    }

    @Override
    public void hide() {
        if (mViewReplacer.getTargetView() != null) {
            final ShimmerFrameLayout shimmerViewContainer = mViewReplacer.getTargetView().findViewById(R.id.shimmer_view_container);
            if (shimmerViewContainer != null) {
                shimmerViewContainer.stopShimmer();
            }
            mViewReplacer.restore();
        }
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
        isViewShowing = false;
        notifyAnimation();
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void onResume() {
        isViewShowing = true;
        notifyAnimation();
    }

    private void notifyAnimation() {

        if (mViewReplacer.getTargetView() != null) {
            final ShimmerFrameLayout shimmerViewContainer = mViewReplacer.getTargetView().findViewById(R.id.shimmer_view_container);
            if (shimmerViewContainer != null) {
                if (isViewShowing) {
                    shimmerViewContainer.startShimmer();
                } else {
                    shimmerViewContainer.stopShimmer();
                }
            }
        }
    }

    public static class Builder {
        private final View mView;
        private int mSkeletonLayoutResID;
        private boolean mShimmer = true;
        private int mShimmerColor;
        private int mShimmerDuration = 1000;
        private int mShimmerAngle = 20;
        private Lifecycle lifecycleRegistry;

        public Builder(View view) {
            this.mView = view;
            this.mShimmerColor = ContextCompat.getColor(mView.getContext(), R.color.shimmer_color);
        }


        public Builder lifecycle(Lifecycle lifecycleRegistry) {
            this.lifecycleRegistry = lifecycleRegistry;
            return this;
        }

        /**
         * @param skeletonLayoutResID the loading skeleton layoutResID
         */
        public Builder load(@LayoutRes int skeletonLayoutResID) {
            this.mSkeletonLayoutResID = skeletonLayoutResID;
            return this;
        }

        /**
         * @param color the shimmer color
         */
        public Builder color(@ColorRes int color) {
            this.mShimmerColor = ContextCompat.getColor(mView.getContext(), color);
            return this;
        }

        /**
         * @param shimmer whether show shimmer animation
         */
        public ViewSkeletonScreen.Builder shimmer(boolean shimmer) {
            this.mShimmer = shimmer;
            return this;
        }

        /**
         * the duration of the animation , the time it will take for the highlight to move from one end of the layout
         * to the other.
         *
         * @param shimmerDuration Duration of the shimmer animation, in milliseconds
         */
        public ViewSkeletonScreen.Builder duration(int shimmerDuration) {
            this.mShimmerDuration = shimmerDuration;
            return this;
        }

        /**
         * @param shimmerAngle the angle of the shimmer effect in clockwise direction in degrees.
         */
        public ViewSkeletonScreen.Builder angle(@IntRange(from = 0, to = 30) int shimmerAngle) {
            this.mShimmerAngle = shimmerAngle;
            return this;
        }

        public ViewSkeletonScreen show() {
            ViewSkeletonScreen skeletonScreen = new ViewSkeletonScreen(this);
            skeletonScreen.show();
            return skeletonScreen;
        }

    }
}
